package Model
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	import mx.collections.ArrayCollection;
	import mx.core.FlexGlobals;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	import mx.events.PropertyChangeEvent;
	import mx.resources.IResourceManager;
	import mx.resources.ResourceManager;
	
	import Controller.AreasController;
	import Controller.OverviewPaletteController;

	public class Areas extends EventDispatcher
	{
		private var _heatedSpaceAreas:ArrayCollection;
		private var _heatedSpaceVolumes:ArrayCollection;
		private var _solidComponents:ArrayCollection;
		private var _totalHeatedSpaceArea:Number;
		private var _totalHeatedSpaceVolume:Number;
		private var _selectedSystem:String = "";
		private var _propertyChangedEvent:Event = new Event("changedProperty");
		private static var overviewPaletteController:OverviewPaletteController = new OverviewPaletteController();
		private var areasController:AreasController = new AreasController();
		private var resourceManager:IResourceManager = ResourceManager.getInstance();
		
		public function Areas()
		{
			this._totalHeatedSpaceArea = 0;
			this._selectedSystem = "";
			this._heatedSpaceAreas = new ArrayCollection();
			this._heatedSpaceAreas.addItem(new HeatedSpaceArea("Living Area LA01"));
			this._heatedSpaceAreas.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleHeatedSpaceAreasChange);
			this._heatedSpaceVolumes = new ArrayCollection();
			this._heatedSpaceVolumes.addItem(new HeatedSpaceVolume("Volume HV01"));
			this.heatedSpaceVolumes.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleHeatedSpaceVolumesChange);
			this._solidComponents = new ArrayCollection();
			this._solidComponents.addEventListener(CollectionEvent.COLLECTION_CHANGE, handleSolidComponentsChange);
			this._solidComponents.addItem(new ComplexSolidComponent(resourceManager.getString('systemtexts','exteriorWallToAmbientAir')));
			this._solidComponents.addItem(new ComplexSolidComponent(resourceManager.getString('systemtexts','exteriorWallToAmbientAir')));
			this._solidComponents.addItem(new ComplexSolidComponent(resourceManager.getString('systemtexts','exteriorWallToAmbientAir')));
			this._solidComponents.addItem(new ComplexSolidComponent(resourceManager.getString('systemtexts','exteriorWallToAmbientAir')));
			this._solidComponents.addItem(new SolidComponent(resourceManager.getString('systemtexts','roofAreaSloped')));
			this._solidComponents.addItem(new SolidComponent(resourceManager.getString('systemtexts','groundSlab')));
			this.addEventListener("changedProperty", handleChangedProperty);
		}
		
		protected function handleChangedProperty(event:Event):void
		{
			this.areasController.updateAreaOverviewSection();
		}
		
		protected function handleSolidComponentsChange(event:CollectionEvent):void
		{
			if(event.kind == CollectionEventKind.UPDATE)
			{
				for each(var changedItem:PropertyChangeEvent in event.items)
				{
					if(changedItem.property != "construction")
					{
						overviewPaletteController.updateOpaqueConstructionsSectionData();
					}

				}
				
			}
			else if(event.kind == CollectionEventKind.RESET)
			{
				areasController.emptyTheCoponentsDropDonwListDataProvider();
			}
			
			else if(event.items[0] is ComplexSolidComponent)
			{ 
				if(event.kind == CollectionEventKind.ADD)
				{
				 	areasController.addIdToComponentsDropDownListDataProvider((event.items[0] as ComplexSolidComponent).id);
				}
				else if(event.kind == CollectionEventKind.REMOVE)
				{
					areasController.removeIdFromComponentsDropDownListsDataProvider((event.items[0] as ComplexSolidComponent).id);
				}
			}
			
			
			FlexGlobals.topLevelApplication.resetCalculations();
		}
		
		protected function handleHeatedSpaceAreasChange(event:CollectionEvent):void
		{
			this.calculateTotalHeatedSpaceArea();
		}
		
		protected function handleHeatedSpaceVolumesChange(event:CollectionEvent):void
		{
			this.calculateTotalHeatedSpaceVolume();
			
		}
/// Heated Space Areas methods	
		private function calculateTotalHeatedSpaceArea():void
		{
			var result:Number = 0;
			
			for each(var heatedSpaceArea:HeatedSpaceArea in this._heatedSpaceAreas)
			{
				result += heatedSpaceArea.area;
			}
			
			this.totalHeatedSpaceArea = result;
		}
		
		private function calculateTotalHeatedSpaceVolume():void
		{
			var result:Number = 0;
			
			for each(var heatedSpaceVolume:HeatedSpaceVolume in this._heatedSpaceVolumes)
			{
				result += heatedSpaceVolume.volume;
			}
			
			this.totalHeatedSpaceVolume = result;
		}
		
		public function get heatedSpaceAreas():ArrayCollection
		{
			return _heatedSpaceAreas;
		}
		
		public function set heatedSpaceAreas(value:ArrayCollection):void
		{
			_heatedSpaceAreas = value;
		}
		
		public function get totalHeatedSpaceArea():Number
		{
			return _totalHeatedSpaceArea;
		}
		
		public function set totalHeatedSpaceArea(value:Number):void
		{
			_totalHeatedSpaceArea = value;
			this.dispatchEvent(this._propertyChangedEvent);
		}
		
		public function addHeatedSpaceArea(heatedSpaceArea:HeatedSpaceArea):void
		{
			this._heatedSpaceAreas.addItem(heatedSpaceArea);
		}
		
		public function removeHeatedSpaceArea(heatedSpaceArea:HeatedSpaceArea):void
		{
			 this._heatedSpaceAreas.removeItemAt(this._heatedSpaceAreas.getItemIndex(heatedSpaceArea));
		}
		
		public function getHeatedSpaceAreaById(id:String):HeatedSpaceArea
		{
			var result:HeatedSpaceArea;
			
			for each (var heatedSpaceArea:SimpleComponent in this._heatedSpaceAreas)
			{
				if(heatedSpaceArea.id == id)
				{
					result = heatedSpaceArea as HeatedSpaceArea;
				}
			}
			
			return result;
		}

		
///Heated Space Volumes methods
		public function get totalHeatedSpaceVolume():Number
		{
			return _totalHeatedSpaceVolume;
		}
		
		public function set totalHeatedSpaceVolume(value:Number):void
		{
			_totalHeatedSpaceVolume = value;
			this.dispatchEvent(this._propertyChangedEvent);
		}

		public function get heatedSpaceVolumes():ArrayCollection
		{
			return _heatedSpaceVolumes;
		}
		
		public function set heatedSpaceVolumes(value:ArrayCollection):void
		{
			_heatedSpaceVolumes = value;
		}
		
		public function addHeatedSpaceVolume(heatedSpaceVolume:HeatedSpaceVolume):void
		{
			this._heatedSpaceVolumes.addItem(heatedSpaceVolume);
		}
		
		public function removeHeatedSpaceVolume(heatedSpaceVolume:HeatedSpaceVolume):void
		{
			this._heatedSpaceVolumes.removeItemAt(this._heatedSpaceVolumes.getItemIndex(heatedSpaceVolume));
		}
		
		public function getHeatedSpaceVolumeById(id:String):HeatedSpaceVolume
		{
			var result:HeatedSpaceVolume;
			
			for each(var heatedSpaceVolume:HeatedSpaceVolume in this._heatedSpaceVolumes)
			{
				if(heatedSpaceVolume.id == id)
				{
					result = heatedSpaceVolume;
				}
			}
			
			return result;
		}

///Solid Components Methods
		
		public function get solidComponents():ArrayCollection
		{
			return _solidComponents;
		}
		
		public function set solidComponents(value:ArrayCollection):void
		{
			_solidComponents = value;
		}
		
		public function addSolidComponent(solidComponent:SolidComponent):void
		{
			this._solidComponents.addItem(solidComponent);
		}
		
		public function removeSolidComponent(solidComponent:SolidComponent):void
		{
			this._solidComponents.removeItemAt(this._solidComponents.getItemIndex(solidComponent));
		}
		
		public function getSolidComponentById(id:String):SolidComponent
		{
			var result:SolidComponent;
			
			for each(var solidComponent:SolidComponent in this._solidComponents)
			{
				if(solidComponent.id == id)
				{
					result = solidComponent;
				}
			}
			
			return result;
		}
		
		public function getComplexSolidComponentById(id:String):ComplexSolidComponent
		{
			var result:ComplexSolidComponent;
			
			for each(var solidComponent:Object in this._solidComponents)
			{
				if(solidComponent.id == id)
				{
					result = solidComponent as ComplexSolidComponent;
				}
			}
			
			return result;
		}
		
		public function getSolidComponentsByType(type:String):ArrayCollection
		{
			var result:ArrayCollection = new ArrayCollection();
			
			for each(var solidComponent:SolidComponent in this._solidComponents)
			{
				if(solidComponent.description == type)
				{
					result.addItem(solidComponent);
				}
			}
			
			return result;
		}
		
		public function getSolidComponentsWithAttachedConstructionsByType(type:String):ArrayCollection
		{
			var result:ArrayCollection = new ArrayCollection();
			
			for each(var solidComponent:SolidComponent in this.getSolidComponentsByType(type))
			{
				if(solidComponent.construction != null)
				{
					result.addItem(solidComponent);
				}
			}
			
			return result;
		}
		
		public function calculateMeanUValueOfSolidComponentsByType(type:String):Number
		{
			var result:Number = 0;
			var totalArea:Number = 0;
			for each(var solidComponent:SolidComponent in this.getSolidComponentsWithAttachedConstructionsByType(type))
			{
				result+= solidComponent.area * solidComponent.construction.uValue;
				totalArea+= solidComponent.area;
			}
			
			return result/totalArea
		}
		
		public function detachConstructionBySolidComponentId(id:String):void
		{
			getSolidComponentById(id).construction = null;
			this.solidComponents.itemUpdated(getSolidComponentById(id), getSolidComponentById(id).construction);
		}
		
		public function solidComponentWithIdExists(id:String):Boolean
		{
			var result:Boolean =  false;
			
			for each (var component:SimpleComponent in this.solidComponents)
			{
				if(component.id  == id)
				{
					result = true;
				}
			}
			
			return result;
			
		}
		

//Windows Methods
		
		public function getWindowParent(window:TransparentComponent):ComplexSolidComponent
		{
			return getSolidComponentById(window.parentComponent) as ComplexSolidComponent;	
		}
		
		public function getWindowById(id:String):TransparentComponent
		{
			var result:TransparentComponent;
			
			for each (var window:TransparentComponent in getAllWindows())
			{
				if(window.id == id)
				{
					result = window;
				}
			}
			
			return result;
		}
		
		public function detachConstrcutionByWindowId(id:String):void
		{
			var window:TransparentComponent =  this.getWindowById(id);
			window.construction = null;
			this.getWindowParent(window).windows.itemUpdated(window, window.construction);
		}
		
		public function getAllWindows():ArrayCollection
		{
			var windows:ArrayCollection = new ArrayCollection();
			
			for each(var solidComponent:Object in this._solidComponents)
			{
				if(solidComponent is ComplexSolidComponent)
				{
					for each(var window:TransparentComponent in (solidComponent as ComplexSolidComponent).windows)
					{
						windows.addItem(window);
					}
				}
			}
			
			return windows;
		}
		
		public function getWindowsWithAttachedConstructions():ArrayCollection
		{
			var result:ArrayCollection = new ArrayCollection();
			
			for each(var window:TransparentComponent in this.getAllWindows())
			{
				if(window.construction != null)
				{
					result.addItem(window);
				}
			}
			
			return result;
		}
		
		public function calculateMeanUValueOfWindows():Number
		{
			var result:Number = 0;
			var totalArea:Number = 0;
			for each(var window:TransparentComponent in this.getWindowsWithAttachedConstructions())
			{
				result+= window.area * window.construction.uValue;
				totalArea+= window.area;
			}
			
			return result/totalArea
		}
		
		public function calculateMeanGValueOfWindowsByOrientation(orientation:String):Number	
		{
			var result:Number = 0;
			var totalArea:Number = 0;
			var number:Number = 0;
				
			for each(var window:TransparentComponent in getWindowsByOrientation(orientation))
			{
				number += window.area * window.construction.gValue;
				totalArea += window.area;
			}
			
			result = number/totalArea;
			
			if(isNaN(result))
			{
				return 0;
			}
			else
			{
				return result;
			}
		}
		
		public function calculateTotalWindowsAreaByOrientation(orientation:String):Number
		{
			var totalArea:Number = 0;
			
			for each(var window:TransparentComponent in getWindowsByOrientation(orientation))
			{
				totalArea += window.area;
			}
			
			return totalArea;
		}
		
		public function getWindowsByOrientation(orientation:String):ArrayCollection
		{		
			var resourceManager:IResourceManager = ResourceManager.getInstance();
			var result:ArrayCollection = new ArrayCollection();
	
			if(orientation == resourceManager.getString('systemtexts','north'))
			{
				for each(var window:TransparentComponent in getWindowsWithAttachedConstructions())
				{
					if((getSolidComponentById(window.parentComponent) as ComplexSolidComponent).orientation == 1)
					{
						result.addItem(window);
					}
				}
			}	
			else if(orientation == resourceManager.getString('systemtexts','northeast'))
			{
				for each(var window:TransparentComponent in getWindowsWithAttachedConstructions())
				{
					if((getSolidComponentById(window.parentComponent) as ComplexSolidComponent).orientation == 45)
					{
						result.addItem(window);
					}
				}
			}
			else if(orientation == resourceManager.getString('systemtexts','east'))
			{
				for each(var window:TransparentComponent in getWindowsWithAttachedConstructions())
				{
					if((getSolidComponentById(window.parentComponent) as ComplexSolidComponent).orientation == 90)
					{
						result.addItem(window);
					}
				}
			}
			else if(orientation == resourceManager.getString('systemtexts','southeast'))
			{
				for each(var window:TransparentComponent in getWindowsWithAttachedConstructions())
				{
					if((getSolidComponentById(window.parentComponent) as ComplexSolidComponent).orientation == 135)
					{
						result.addItem(window);
					}
				}
			}
			else if(orientation == resourceManager.getString('systemtexts','south'))
			{
				for each(var window:TransparentComponent in getWindowsWithAttachedConstructions())
				{
					if((getSolidComponentById(window.parentComponent) as ComplexSolidComponent).orientation == 180)
					{
						result.addItem(window);
					}
				}
			}
			else if(orientation == resourceManager.getString('systemtexts','southwest'))
			{
				for each(var window:TransparentComponent in getWindowsWithAttachedConstructions())
				{
					if((getSolidComponentById(window.parentComponent) as ComplexSolidComponent).orientation == 225)
					{
						result.addItem(window);
					}
				}
			}
			else if(orientation == resourceManager.getString('systemtexts','west'))
			{
				for each(var window:TransparentComponent in getWindowsWithAttachedConstructions())
				{
					if((getSolidComponentById(window.parentComponent) as ComplexSolidComponent).orientation == 270)
					{
						result.addItem(window);
					}
				}
			}
			else if(orientation == resourceManager.getString('systemtexts','northwest'))
			{
				for each(var window:TransparentComponent in getWindowsWithAttachedConstructions())
				{
					if((getSolidComponentById(window.parentComponent) as ComplexSolidComponent).orientation == 315)
					{
						result.addItem(window);
					}
				}
			}
			
			return result;
		}

		public function calculateMeanGValueOfWindows():Number
		{
			var result:Number = 0;
			var totalArea:Number = 0;
			for each(var window:TransparentComponent in this.getWindowsWithAttachedConstructions())
			{
				result+= window.area * window.construction.gValue;
				totalArea+= window.area;
			}
			
			return result/totalArea
		}
		
		public function removeWindow(windowToBeDeleted:TransparentComponent):void
		{
			for each(var solidComponent:Object in this._solidComponents)
			{
				if(solidComponent is ComplexSolidComponent)
				{
					for each(var window:TransparentComponent in (solidComponent as ComplexSolidComponent).windows)
					{
						if(window == windowToBeDeleted)
						{
							(solidComponent as ComplexSolidComponent).windows.removeItemAt((solidComponent as ComplexSolidComponent).windows.getItemIndex(window));
						}
					}
				}
			}
		}

//Doors Methods	
		
		public function getDoorById(id:String):TransparentComponent
		{
			var result:TransparentComponent;
			
			for each (var door:TransparentComponent in this.getAllDoors())
			{
				if(door.id == id)
				{
					result = door;
				}
			}
			
			return result;
		}
		
		public function detachConstructionByDoorId(id:String):void
		{
			var door:TransparentComponent = this.getDoorById(id);
			door.construction = null;
			this.getDoorParent(door).doors.itemUpdated(door, door.construction);
		}
		
		public function getAllDoors():ArrayCollection
		{
			var doors:ArrayCollection = new ArrayCollection();
			
			for each(var solidComponent:Object in this._solidComponents)
			{
				if(solidComponent is ComplexSolidComponent)
				{
					for each(var door:TransparentComponent in (solidComponent as ComplexSolidComponent).doors)
					{
						doors.addItem(door);
					}
				}
			}
			
			return doors;
		}
		
		public function getDoorParent(door:TransparentComponent):ComplexSolidComponent
		{
			return this.getSolidComponentById(door.parentComponent) as ComplexSolidComponent;
		}
		
		public function getDoorsWithAttachedConstructions():ArrayCollection
		{
			var result:ArrayCollection = new ArrayCollection();
			
			for each(var door:TransparentComponent in this.getAllDoors())
			{
				if(door.construction != null)
				{
					result.addItem(door);
				}
			}
			
			return result;
		}
		
		public function calculateMeanUValueOfDoors():Number
		{
			var result:Number = 0;
			var totalArea:Number = 0;
			for each(var door:TransparentComponent in this.getDoorsWithAttachedConstructions())
			{
				result+= door.area * door.construction.uValue;
				totalArea+= door.area;
			}
			
			return result/totalArea
		}
		
		
		public function removeDoor(doorToBeDeleted:TransparentComponent):void
		{	
			for each(var solidComponent:Object in this._solidComponents)
			{
				if(solidComponent is ComplexSolidComponent)
				{
					for each(var door:TransparentComponent in (solidComponent as ComplexSolidComponent).doors)
					{
						if(door == doorToBeDeleted)
						{
							(solidComponent as ComplexSolidComponent).doors.removeItemAt((solidComponent as ComplexSolidComponent).doors.getItemIndex(door));
						}
					}
				}
			}
		}
		//checks if there are attached construction to solid components
		//doors or windows
		public function attachedConstructionsExists():Boolean
		{
			var resourceManager:IResourceManager = ResourceManager.getInstance();
			
			if(getSolidComponentsWithAttachedConstructionsByType(resourceManager.getString('systemtexts','exteriorWallToAmbientAir')).length > 0 ||
				getSolidComponentsWithAttachedConstructionsByType(resourceManager.getString('systemtexts','exteriorWallToGround')).length > 0 ||
				getSolidComponentsWithAttachedConstructionsByType(resourceManager.getString('systemtexts','externalWallToCellar')).length > 0 ||
				getSolidComponentsWithAttachedConstructionsByType(resourceManager.getString('systemtexts','externalWallPartitionWall')).length > 0 ||
				getSolidComponentsWithAttachedConstructionsByType(resourceManager.getString('systemtexts','roofAreaSloped')).length > 0 ||
				getSolidComponentsWithAttachedConstructionsByType(resourceManager.getString('systemtexts','roofAreaFlat')).length > 0 ||
				getSolidComponentsWithAttachedConstructionsByType(resourceManager.getString('systemtexts','groundSlab')).length > 0 ||
				getSolidComponentsWithAttachedConstructionsByType(resourceManager.getString('systemtexts','groundSlabAgainstCellar')).length > 0 ||
				getWindowsWithAttachedConstructions().length > 0 ||
				getDoorsWithAttachedConstructions().length > 0)
				{
					return true;
				}
				
				else
				{
					return false;
				}
				
		}
		
		public function getThermlaEnvelopeArea():Number
		{
			var result:Number = 0;
			
			for each(var solidComponent:SolidComponent in this.solidComponents)
			{
				result+= solidComponent.area;
			}
			
			for each(var door:TransparentComponent in this.getAllDoors())
			{
				result += door.area
			}
			
			for each(var window:TransparentComponent in this.getAllWindows())
			{
				result += window.area
			}
			
			return result;
		}

		public function calculateVARation():Number
		{
			if(totalHeatedSpaceArea== 0)
				return 0;
			return totalHeatedSpaceVolume/totalHeatedSpaceArea;
		}
		public function get selectedSystem():String
		{
			return _selectedSystem;
		}

		public function set selectedSystem(value:String):void
		{
			_selectedSystem = value;
		}

	}
}